package com.jushu.storbox.task.tqueue;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import android.content.Context;

import com.jushu.storbox.R;
import com.jushu.storbox.ShareDriveApplication;
import com.jushu.storbox.callback.ICallback;
import com.jushu.storbox.callback.IShareDownloadCallback;
import com.jushu.storbox.constant.ClientConfig;
import com.jushu.storbox.constant.Constant;
import com.jushu.storbox.database.DAOFactory;
import com.jushu.storbox.entities.FileFolderInfo;
import com.jushu.storbox.filesystem.FileManagerFactory;
import com.jushu.storbox.filesystem.iFileManager;
import com.jushu.storbox.manager.ShareDownloadTaskManager;
import com.jushu.storbox.service.FileHelper;
import com.jushu.storbox.util.DirectoryUtil;
import com.jushu.storbox.util.FileUtil;
import com.jushu.storbox.util.LogUtil;
import com.huawei.sharedrive.sdk.android.exception.ClientException;
import com.huawei.sharedrive.sdk.android.serviceV2.AbsDownloadProcessorV3;
import com.huawei.sharedrive.sdk.android.serviceV2.FileClientV2;
import com.huawei.sharedrive.sdk.android.serviceV2.IDownloadProcessorV2;

public class ShareDownloadTask extends ShareDownloadPriorityTask {

	private final static String TAG = "DownloadTask";
	private Context context;
	private Random random;
	private int priority;
	private final String id;
	private String ownerID;
	private final String fileID;
	private String authorization;
	private long startIndex;
	private String path;
	private ICallback callback = null;
	private FileClientV2 client = null;
	private final String folderID;
	private final long fileSize;
	private int isInode;
	FileFolderInfo mFileFolderInfo;
	
	private boolean isCancel = false;
	
	private boolean isStop = false;
	
	private String tempPath = "";
	
	public ShareDownloadTask(Context context, String ownerID, String folderID, String fileID,
			long startIndex, long fileSize, String path,
			ICallback callback,FileFolderInfo fileFolderInfo,int isInode) {
		this.context = context;
		random = new Random();
		this.priority = Math.abs(random.nextInt() % 10);
		this.id = fileID;
		this.ownerID = ownerID;
		this.folderID = folderID;
		this.fileID = fileID;
		this.authorization = ShareDriveApplication.getInstance().getAuthorization();
		this.startIndex = startIndex;
		this.path = path;
		this.isCancel = false;
		this.isInode = isInode;
		mFileFolderInfo = fileFolderInfo;
		if (null == callback) {
			callback = new IShareDownloadCallback() {
				
				@Override
				public void onSuccess() {
				}
				
				@Override
				public void onStart() {
				}
				
				@Override
				public void onProgress(int currentProgress, long currentSize, long maxSize) {
				}
				
				@Override
				public void onFailure(Throwable t,int statusCode) {
				}

				@Override
				public void onStop() {
				}

				@Override
				public void onCanceled() {
				}

				@Override
				public void onDettach() {
				}
			};
		}
    	tempPath  = DirectoryUtil.generateTempShareDownloadPath(context, mFileFolderInfo.getOwnerBy(), mFileFolderInfo.getiNodeId(), mFileFolderInfo.getName());
		this.callback = callback;
		if (null == client)
			client = FileClientV2.getInstance();
		this.fileSize = fileSize;
		if(isInode == Constant.DOWNLOAD_STATUS_INODE){
			DAOFactory.instance(context).getShareINodeDao().updateTransStatus(Constant.DOWNLOAD_ISWAITING_UPDATE_DB, fileID,ownerID);
		}else{
			DAOFactory.instance(context).getShareFileDao().updateTransStatus(Constant.DOWNLOAD_ISWAITING_UPDATE_DB, fileID,ownerID);
		}
	}
	
	public long getFileSize(){
    	return fileSize;
    }
	
	public String getId() {
		return id;
	}

	public String getFolderID() {
		return folderID;
	}

	@Override
	public int getPriority() {
		// TODO Auto-generated method stub
		return priority;
	}
	
	@Override
	public void setPriority(int priority) {
		// TODO Auto-generated method stub
		this.priority = priority;
	}
	
	@Override
	public void setTipTopPriority() {
		// TODO Auto-generated method stub
		this.priority = Integer.MAX_VALUE;
	}
	
	public void cancelDownloadTask(Context context) {
		this.isCancel = true;
		ShareDownloadTaskManager.removeTask(this);
		deleteSelfFile(context);
	}
	
	public void deleteSelfFile(Context context) {
	    iFileManager mdmTools = FileManagerFactory.getFileManager(context);
		mdmTools.deleteFile(tempPath);
	}
	
	public String getPath() {
		return path;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			if (null != client) {
				ShareDownloadTaskManager.addRunningTask(this);
				ShareDownloadTaskManager.removeWaitingTask(this);
//				DAOFactory.instance(context).getFileDao().updateTransStatus(Constant.DOWNLOAD_ISRUNNING_UPDATE_DB, fileID);
				if(isInode == Constant.DOWNLOAD_STATUS_INODE){
					DAOFactory.instance(context).getShareINodeDao().updateTransStatus(Constant.DOWNLOAD_ISWAITING_UPDATE_DB, fileID,ownerID);
				}else{
					DAOFactory.instance(context).getShareFileDao().updateTransStatus(Constant.DOWNLOAD_ISWAITING_UPDATE_DB, fileID,ownerID);
				}
				if (null == this.id || "".equalsIgnoreCase(this.id.trim())) {
					Exception e = new Exception("fileID is null");
					LogUtil.e(TAG, "[" + tempPath + "]" + e.getLocalizedMessage());
					callback.onFailure(e.fillInStackTrace(),0);// onFail
					ShareDownloadTaskManager.addFailTask(ShareDownloadTask.this);
				} else {
					//
					AbsDownloadProcessorV3 processor = new AbsDownloadProcessorV3() {
												
						@Override
						public void onTaskFailure(int errorCode, String errorMsg) {
							ClientException e = new ClientException(errorCode, errorMsg);
							e.printStackTrace();
							LogUtil.e(TAG, "[" + tempPath + "]" + e.getLocalizedMessage());
							
							ShareDownloadTaskManager.addFailTask(ShareDownloadTask.this);
							
							if(isInode == Constant.DOWNLOAD_STATUS_INODE){
								DAOFactory.instance(context).getShareINodeDao().updateTransStatus(Constant.DOWNLOAD_FAIL_UPDATE_DB, fileID,ownerID);
							}else{
								DAOFactory.instance(context).getShareFileDao().updateTransStatus(Constant.DOWNLOAD_FAIL_UPDATE_DB, fileID,ownerID);
							}
							
							if(isInode == Constant.DOWNLOAD_STATUS_INODE){
								DAOFactory.instance(context).getShareINodeDao().updateSyncStatuc(Constant.DOWNLOAD_STATUS_NOCACHE_DB, fileID, ownerID);
							}else{
								DAOFactory.instance(context).getShareFileDao().updateSyncStatus(Constant.DOWNLOAD_STATUS_NOCACHE_DB, fileID, ownerID);
							}
							callback.onFailure(e.fillInStackTrace() ,e.getStatusCode());
						}

						@Override
						public long getFileSize(String arg0) {
							return fileSize;
						}

						@Override
						public long getStartIndex(String arg0) {
							if(startIndex > 0){
								return startIndex;
							}
							File file = new File(tempPath);
                    		if(file.exists()) {
                            	LogUtil.i(TAG, "[NONMDM] temp file is exist!");
                				startIndex = file.length();
                				if (fileSize == startIndex) {
                					startIndex = fileSize - 10;
                					startIndex = 0;
                				}
                    		} else {
                            	LogUtil.i(TAG, "[NONMDM] temp file is not exist!");
                            	startIndex = 0;
                    		}
                        	LogUtil.i(TAG, "[NONMDM] start Index is: "+startIndex);
	                        return startIndex;
						}

						@Override
						protected void onDownloadStart(long currentPosition,
								long maxSize) {
							callback.onStart();// start
						}

						@Override
						protected File getTargetFile() {
							return new File(tempPath);
						}

						@Override
						protected void onProgress(int progress,
								long currentSize, long totalSize) {
							callback.onProgress(progress, currentSize, totalSize);
						}

						@Override
						protected boolean requestCancelTask() {
							return ShareDownloadTask.this.isCancel;
						}

						@Override
						protected void onTaskCanceled() {
                            Exception e = new Exception("cancel cache success!");
                            LogUtil.e(TAG, "[" + tempPath + "]" + e.getLocalizedMessage());
                            
                            ShareDownloadTaskManager.addFailTask(ShareDownloadTask.this);
                            
                            if(isInode == Constant.DOWNLOAD_STATUS_INODE){
                                DAOFactory.instance(context).getShareINodeDao().updateTransStatus(Constant.DOWNLOAD_CANCEL_UPDATE_DB, fileID,ownerID);
                            }else{
                                DAOFactory.instance(context).getShareFileDao().updateTransStatus(Constant.DOWNLOAD_CANCEL_UPDATE_DB, fileID,ownerID);
                            }
                            
                            callback.onFailure(e.fillInStackTrace(), Constant.DOWNLOAD_CANCEL_SUCCESS_CODE);// onFail
						}

						@Override
						protected boolean requestStopTask() {
							return ShareDownloadTask.this.isStop;
						}

						@Override
						protected void onTaslStoped() {
						}

						@Override
						protected void onTaskSuccess() {
							boolean moveFlag = FileUtil.renameFile(tempPath, path);
                        	if(moveFlag){
                        		callback.onSuccess();// onSuccess
                                if(isInode == Constant.DOWNLOAD_STATUS_INODE){
                                    DAOFactory.instance(context).getShareINodeDao().updateTransStatus(Constant.DOWNLOAD_SUCCESS_UPDATE_DB, fileID,ownerID);
                                }else{
                                    DAOFactory.instance(context).getShareFileDao().updateTransStatus(Constant.DOWNLOAD_SUCCESS_UPDATE_DB, fileID,ownerID);
                                }
                        	}
						}

						@Override
						protected void InputStreamIsInvalid() {
							LogUtil.e(TAG,"the input stream is invalid!");
						}

						@Override
						protected long getAvalibleSpace() {
							double freeSpace = FileHelper.getUsingSDCardSize(context, DirectoryUtil
				    				.getCurrentCachePath(context)+ClientConfig.CACHE_CONTEXT);
							return (long) freeSpace;
						}

						@Override
						protected void onSystemSpaceNotEnough() {
							if(isInode == Constant.DOWNLOAD_STATUS_INODE){
								DAOFactory.instance(context).getShareINodeDao().updateTransStatus(Constant.DOWNLOAD_CONTENT_NOT_SYNCHRONIZATION, fileID,ownerID);
							} else {
								DAOFactory.instance(context).getShareFileDao().updateTransStatus(Constant.DOWNLOAD_CONTENT_NOT_SYNCHRONIZATION, fileID,ownerID);
							}
			        		callback.onFailure(new ClientException(context.getString(R.string.download_file_larger_than_local_cache)), Constant.DOWNLOAD_FAIL_FILE_LARGERTHAN_CACHESIZE);
							super.onSystemSpaceNotEnough();
						}
                        
					};
					client.download(ownerID, fileID, null, authorization, processor);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			LogUtil.e(TAG, "[" + tempPath + "]" + e.getLocalizedMessage());
			ShareDownloadTaskManager.addFailTask(ShareDownloadTask.this);
			callback.onFailure(e.fillInStackTrace(),0);
		} finally {
			ShareDownloadTaskManager.removeTask(ShareDownloadTask.this);
		}
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ShareDownloadTask other = (ShareDownloadTask) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equalsIgnoreCase(other.id))
			return false;
		return true;
	}

	// callback
	public void setCallback(IShareDownloadCallback callback) {
		this.callback = callback;
	}
}
